#pragma once

#include "mono/pch.h"
#include "mono/Method.h"

namespace mono
{
    struct Object
    {
        MonoObject *object;

        MonoClass *klass;

        Object() : object(0), klass(0) {}

        Object(MonoObject *obj, MonoClass *klz)
            : object(obj), klass(klz) {

            Init();
        };

        bool Init()
        {
            ztclog::debug("init class");

            mono_runtime_object_init(object);

            void *iter = nullptr;

            MonoClassField *field = nullptr;

            while ((field = mono_class_get_fields(klass, &iter)))
            {
                const char *fieldName = mono_field_get_name(field);
                MonoType *fieldType = mono_field_get_type(field);

                ztclog::debug("the Field is %s", fieldName);

                MonoObject *fieldValueObj = nullptr;
                mono_field_get_value(object, field, &fieldValueObj);

                // Is Null
                ztclog::debug("the field obj is %p", fieldValueObj);

                if (fieldValueObj)
                {
                    MonoClass *fieldValueClass = mono_object_get_class(fieldValueObj);
                    const char *fieldValueClassName = mono_class_get_name(fieldValueClass);
                    ztclog::info("Type: %s", fieldValueClassName);
                }

            }
            return true;
        };

        MonoObject *Invoke(mono::Method *method, mono::Args args)
        {
            MonoObject *result = 0;
            auto returnType = method->Invoke(args, this->object);
            // ztclog::debug("return %p ");
            // mono_field_get_value(obj, field, &fieldValueObj);

            return returnType;
        }

        template <typename T>
        bool Invoke2(mono::Method *method, mono::Args args, T &t)
        {
            auto result = Invoke(method, args);
            mono::Converter<T> converter;
            return converter.Decode(result, t);
        };
    };
};